package it.trekker.dao;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Transient;

@Entity
public class Excursion implements Serializable {

	protected int id;
	protected String name;
	protected Date date;
	private double distance;
	private double totAltitudeDifference;
	private long time;
	private double meanPace;
	protected long steps;
	protected Set<ExcursionCoordinate> coordinates;
	protected Set<Photo> photos;
	protected Set<Poi> pois;
	protected User user;
	
	public Excursion() {
		this(-1, null, null);
	}
	
	public Excursion(String name) {
		this(-1, name, null);
	}
	
	public Excursion(int id, String name, Date date) {
		this.id = id;
		this.name = name;
		this.date = date;
		this.steps = 0;
	}
	
	public Excursion(Excursion excursion) {
		if(excursion != null) {
			this.id = -1;
			this.name = excursion.getName();
			this.date = excursion.getDate();
			this.distance = excursion.getDistance();
			this.totAltitudeDifference = excursion.getTotAltitudeDifference();
			this.time = excursion.getTime();
			this.meanPace = excursion.getMeanPace();
			this.steps = excursion.steps;
		}
	}

	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}
	
	public double getDistance() {
		return distance;
	}

	public void setDistance(double distance) {
		this.distance = distance;
	}

	public double getTotAltitudeDifference() {
		return totAltitudeDifference;
	}

	public void setTotAltitudeDifference(double totAltitudeDifference) {
		this.totAltitudeDifference = totAltitudeDifference;
	}

	public long getTime() {
		return time;
	}

	public void setTime(long time) {
		this.time = time;
	}

	public double getMeanPace() {
		return meanPace;
	}

	public void setMeanPace(double meanPace) {
		this.meanPace = meanPace;
	}
	
	public long getSteps() {
		return steps;
	}

	public void setSteps(long steps) {
		this.steps = steps;
	}

	@OrderBy("timestamp ASC")
	@OneToMany(
			fetch = FetchType.LAZY,
			cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH},
			mappedBy = "excursion"
	)
	public Set<ExcursionCoordinate> getCoordinates() {
		return coordinates;
	}

	public void setCoordinates(Set<ExcursionCoordinate> coordinates) {
		this.coordinates = coordinates;
	}

	@OneToMany(
			fetch = FetchType.LAZY,
			cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH},
			mappedBy = "excursion"
	)
	public Set<Photo> getPhotos() {
		return photos;
	}

	public void setPhotos(Set<Photo> photos) {
		this.photos = photos;
	}

	@OneToMany(
			fetch = FetchType.LAZY,
			cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.REFRESH},
			mappedBy = "excursion"
	)
	public Set<Poi> getPois() {
		return pois;
	}

	public void setPois(Set<Poi> pois) {
		this.pois = pois;
	}

	@Transient
	public GPSCoordinate getStartPoint() {
		if(coordinates != null && coordinates.size() > 0)
			return coordinates.iterator().next().getCoordinate();
		
		return null;
	}
	
	@Transient
	public GPSCoordinate getEndPoint() {
		if(coordinates != null && coordinates.size() > 0) {
			List<ExcursionCoordinate> list = new ArrayList<ExcursionCoordinate>(coordinates);
			return list.get(list.size()-1).getCoordinate();
		}
		
		return null;
	}

	@ManyToOne(
			fetch = FetchType.EAGER,
			cascade = {CascadeType.PERSIST}
	)
	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	@Override
	public String toString() {
		return String.format("id: %d - name: %s - date: %s", id, name, date);
	}
}
